package info.niwota.search;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Random;

import org.htmlparser.Parser;
import org.htmlparser.util.ParserException;
import org.htmlparser.visitors.TextExtractingVisitor;

public class TextCooker {
	//random text
	private static String[] spices = {""};
	
	static {
		initSpices();
	}
	
	private final Random rand = new Random();
	private final String stag = "<p ";
	private final String etag = "</p>";
	
	private String[] spiceClass;
	
	private String[] chopClass;
	
	private String style;
	
	public TextCooker() {
		init(10);
	}
	
	protected void init(int max) {
		final int min = 3;
		spiceClass = new String[rand.nextInt(max) + min];
		chopClass = new String[rand.nextInt(max) + min];
		
		int sc = rand.nextInt(max);
		
		for (int i = 0, j = 0; i < spiceClass.length || j < chopClass.length;) {
			sc += rand.nextInt(max) + 1;
			
			String c = "c" + sc;
			if (sc % 2 == 0) {
				if (i < spiceClass.length) {
					spiceClass[i++] = c;
				} else {
					chopClass[j++] = c;
				}
			} else {
				if (j < chopClass.length) {
					chopClass[j++] = c;
				} else {
					spiceClass[i++] = c;
				}
			}
		}
		
		StringBuilder sb = new StringBuilder();
		
		for (int i = 0; i < spiceClass.length; i++) {
			sb.append("." + spiceClass[i]+" {display: none;} ");
		}
		
		for (int i = 0; i < chopClass.length; i++) {
			sb.append("." + chopClass[i] +" {display: inline;} ");
		}
		
		style = sb.toString();
	}
	
	public String cook(String text, int max) {
		StringBuilder sb = new StringBuilder();
		cook(text, max, sb);
		return sb.toString();
	}

	public void cook(String text, int max, StringBuilder cooked) {
		final int len = text.length();
	
		if (len <= max) {
			cooked.append(text);
			return;
		}
		
		for (int i = 0, n = 1; i < len; i += n) {
			n = Math.min(rand.nextInt(max) + 1, len - i);
			String chop = text.substring(i, i + n);
			
			String sc = chopClass[rand.nextInt(chopClass.length)];
			
			cooked.append(stag + "class=\""+ sc +"\">");
			cooked.append(chop);
			cooked.append(etag);
			
			//randomness
			if (n % 2 == 0) {
				continue;
			}
			
			String spice = spices[rand.nextInt(spices.length)];
			
			sc = spiceClass[rand.nextInt(spiceClass.length)];
			
			cooked.append(stag+ "class=\""+ sc +"\">");
			cooked.append(spice);
			cooked.append(etag);
		}
	}
	
	public String getStyle() {
		return style;
	}

	public String getStyleSheet() {
		return "<style type=\"text/css\">"+getStyle()+"</style>";
	}
	
	public static void initSpices() {
		HashSet<String> words= new HashSet<String>();
		
		try {
			extract(new URL("http://www.google.com/trends"), words);
		} catch (Exception e) {
			e.printStackTrace();
		}
		try {
			extract(new URL("http://www.w3.org/"), words);
		} catch (Exception e) {
			e.printStackTrace();
		}
		try {
			extract(new URL("http://www.apache.org/"), words);
		} catch (Exception e) {
			e.printStackTrace();
		}
		//just in case all the above failed
		words.addAll(Arrays.asList(new String[]{"a", "the", "who", "what", "where", "when", "how"}));
		
		spices = words.toArray(new String[0]);
	}
	
	private static HashSet<String> extract(URL url, HashSet<String> words) throws Exception {
		BufferedReader in = null;
		try {
			URLConnection yc = url.openConnection();
			in = new BufferedReader(new InputStreamReader(
					yc.getInputStream()));
			StringBuilder sb = new StringBuilder();
			String line = null;
			while ((line = in.readLine()) != null) {
				sb.append(line);
			}
			String text = extractText(sb.toString());
			String[] sa = text.split("\\s");
			for (int i = 0; i < sa.length; i++) {
				//filter
				if (sa[i].equals("") || sa[i].indexOf("<") != -1 || sa[i].indexOf(">") != -1 || sa[i].length() > 10) {
					continue;
				}
				words.add(sa[i]);
			}
		} finally {
			if (in != null) {
				in.close();
			}
		}
		return words;
	}
	
	private static String extractText(String html) throws ParserException {
		Parser parser = Parser.createParser(html, null);
        TextExtractingVisitor visitor = new TextExtractingVisitor();
        parser.visitAllNodesWith(visitor);
        return visitor.getExtractedText();
	}
	
	public void cook(String text, int max, StringBuilder cooked,
			StringBuilder js) {
		final int len = text.length();

		if (len <= max) {
			cooked.append(text);
			return;
		}

		for (int i = 0, j = 0, n = 1; i < len; i += n) {
			n = Math.min(rand.nextInt(max) + 1, len - i);
			String chop = text.substring(i, i + n);
			cooked.append(chop);

			js.append(j);
			js.append(",");
			js.append(j += n);
			js.append(",");
			js.append(1);
			js.append(",");

			if (n % 2 == 0) {
				continue;
			}

			String spice = spices[rand.nextInt(spices.length)];
			cooked.append(spice);

			js.append(j);
			js.append(",");
			js.append(j += spice.length());
			js.append(",");
			js.append(0);
			js.append(",");
		}
	}
}
